package com.xiyuan.smartutils.enums;

import com.xiyuan.smartutils.DateTimes;
import com.xiyuan.smartutils.annotation.EnumValue;
import com.xiyuan.smartutils.domain.date.DateDimension;
import com.xiyuan.smartutils.domain.date.DateRange;

import java.text.SimpleDateFormat;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

/**
 * 时期维度枚举
 *
 * @author xiyuan-lgz 2025-08-04 @version v1.0.0 新建与整理
 */
public enum DateDimensionEnum {
    DAY(0, "日") {
        @Override
        public List<DateDimension> parseRangeDimension(Date startTime, Date endTime) {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
            List<DateDimension> list = new ArrayList<>();
            Date min = startTime.getTime() >= endTime.getTime() ? endTime : startTime;
            Date max = startTime.getTime() < endTime.getTime() ? endTime : startTime;
            Calendar startCal = Calendar.getInstance();
            startCal.setTime(min);
            startCal.add(Calendar.DAY_OF_MONTH, -1);
            
            Calendar endCal = Calendar.getInstance();
            endCal.setTime(max);
            endCal.set(Calendar.HOUR_OF_DAY, 0);
            endCal.set(Calendar.MINUTE, 0);
            endCal.set(Calendar.SECOND, 0);
            endCal.set(Calendar.MILLISECOND, 0);
            
            do {
                startCal.add(Calendar.DAY_OF_MONTH, 1);
                startCal.set(Calendar.HOUR_OF_DAY, 0);
                startCal.set(Calendar.MINUTE, 0);
                startCal.set(Calendar.SECOND, 0);
                startCal.set(Calendar.MILLISECOND, 0);
                Calendar endCl = (Calendar) startCal.clone();
                endCl.set(Calendar.HOUR_OF_DAY, 23);
                endCl.set(Calendar.MINUTE, 59);
                endCl.set(Calendar.SECOND, 59);
                endCl.set(Calendar.MILLISECOND, 0);
                
                Date sTime = startCal.getTime();
                Date eTime = endCl.getTime();
                if (sTime.before(min)) {
                    sTime = min;
                }
                
                if (eTime.after(max)) {
                    eTime = max;
                }
                list.add(new DateDimension(sdf.format(sTime), new DateRange(sTime, eTime)).setDimension(this));
                if (eTime == max) {
                    break;
                }
                
                
            }
            while (startCal.before(endCal));
            
            return list;
        }
    },
    WEEK(1, "周") {
        @Override
        public List<DateDimension> parseRangeDimension(Date startTime, Date endTime) {
            SimpleDateFormat sdf_date_time = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy");
            List<DateDimension> list = new ArrayList<>();
            Date min = startTime.getTime() >= endTime.getTime() ? endTime : startTime;
            Date max = startTime.getTime() < endTime.getTime() ? endTime : startTime;
            
            Calendar startCal = Calendar.getInstance();
            startCal.setTime(min);
            
            Calendar endCal = Calendar.getInstance();
            endCal.setTime(max);
            if (sdf_date_time.format(max).endsWith("00:00:00")) {
                // 如果查询参数没有携带时分秒那么. 则将结束时间设置为23:59:59
                endCal.set(Calendar.HOUR_OF_DAY, 23);
                endCal.set(Calendar.MINUTE, 59);
                endCal.set(Calendar.SECOND, 59);
                max = endCal.getTime();
            }
            
            // 调整到本周的第一天（周日）
            startCal.set(Calendar.DAY_OF_WEEK, startCal.getFirstDayOfWeek());
            
            // 循环处理每周
            while (startCal.before(endCal)) {
                // 当前周的开始
                Date weekStart = startCal.getTime();
                
                // 计算周的结束（周六）
                Calendar weekEndCal = (Calendar) startCal.clone();
                weekEndCal.add(Calendar.DAY_OF_WEEK, 6);
                weekEndCal.set(Calendar.HOUR_OF_DAY, 23);
                weekEndCal.set(Calendar.MINUTE, 59);
                weekEndCal.set(Calendar.SECOND, 59);
                Date weekEnd = weekEndCal.getTime();
                
                // 如果周结束时间超过了结束时间，使用结束时间
                if (weekEnd.after(max)) {
                    weekEnd = max;
                }
                
                // 格式化周名称
                String weekName = sdf.format(weekStart) + "-" + startCal.get(Calendar.WEEK_OF_YEAR);
                // 添加到结果列表
                list.add(new DateDimension(weekName, new DateRange(weekStart, weekEnd)).setDimension(this));
                
                // 移动到下一周的第一天
                startCal.add(Calendar.WEEK_OF_YEAR, 1);
            }
            
            return list;
        }
    },
    
    QUARTER(2, "季") {
        @Override
        public List<DateDimension> parseRangeDimension(Date startTime, Date endTime) {
            SimpleDateFormat sdf_date_time = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            List<DateDimension> list = new ArrayList<>();
            Date min = startTime.getTime() >= endTime.getTime() ? endTime : startTime;
            Date max = startTime.getTime() < endTime.getTime() ? endTime : startTime;
            
            Calendar startCal = Calendar.getInstance();
            startCal.setTime(min);
            
            Calendar endCal = Calendar.getInstance();
            endCal.setTime(max);
            if (sdf_date_time.format(max).endsWith("00:00:00")) {
                // 如果查询参数没有携带时分秒那么. 则将结束时间设置为23:59:59
                endCal.set(Calendar.HOUR_OF_DAY, 23);
                endCal.set(Calendar.MINUTE, 59);
                endCal.set(Calendar.SECOND, 59);
                max = endCal.getTime();
            }
            
            // 调整到季度的第一天
            int startMonth = startCal.get(Calendar.MONTH);
            int startQuarter = (startMonth / 3) + 1;
            startCal.set(Calendar.MONTH, (startQuarter - 1) * 3);
            startCal.set(Calendar.DAY_OF_MONTH, 1);
            
            // 循环处理每个季度
            while (startCal.before(endCal)) {
                // 当前季度的开始
                Date quarterStart = startCal.getTime();
                
                // 计算季度的结束
                startCal.add(Calendar.MONTH, 2);  // 移动到季度的最后一个月
                startCal.set(Calendar.DAY_OF_MONTH, startCal.getActualMaximum(Calendar.DAY_OF_MONTH));
                Calendar endCl = (Calendar) startCal.clone();
                endCl.set(Calendar.HOUR_OF_DAY, 23);
                endCl.set(Calendar.MINUTE, 59);
                endCl.set(Calendar.SECOND, 59);
                Date quarterEnd = endCl.getTime();
                
                // 如果季度结束时间超过了结束时间，使用结束时间
                if (quarterEnd.after(max)) {
                    quarterEnd = max;
                }
                
                // 格式化季度名称
                int year = startCal.get(Calendar.YEAR);
                int quarter = (startCal.get(Calendar.MONTH) / 3) + 1;
                String quarterName = year + "-" + quarter;
                
                // 添加到结果列表
                list.add(new DateDimension(quarterName, new DateRange(quarterStart, quarterEnd)).setDimension(this));
                
                // 移动到下一个季度的第一天
                startCal.add(Calendar.MONTH, 1); // 移动到下个季度的第一个月
                startCal.set(Calendar.DAY_OF_MONTH, 1);
            }
            
            return list;
        }
    },
    
    MONTH(3, "月") {
        @Override
        public List<DateDimension> parseRangeDimension(Date startTime, Date endTime) {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM");
            SimpleDateFormat sdf_date_time = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            Date min = startTime.getTime() >= endTime.getTime() ? endTime : startTime;
            Date max = startTime.getTime() < endTime.getTime() ? endTime : startTime;
            List<DateDimension> list = new ArrayList<>();
            
            Calendar startCal = Calendar.getInstance();
            startCal.setTime(min);
            
            Calendar endCal = Calendar.getInstance();
            endCal.setTime(max);
            if (sdf_date_time.format(max).endsWith("00:00:00")) {
                // 如果查询参数没有携带时分秒那么. 则将结束时间设置为23:59:59
                endCal.set(Calendar.HOUR_OF_DAY, 23);
                endCal.set(Calendar.MINUTE, 59);
                endCal.set(Calendar.SECOND, 59);
                max = endCal.getTime();
            }
            
            // 调整到月份的第一天
            startCal.set(Calendar.DAY_OF_MONTH, 1);
            startCal.set(Calendar.HOUR_OF_DAY, 0);
            startCal.set(Calendar.MINUTE, 0);
            startCal.set(Calendar.SECOND, 0);
            startCal.set(Calendar.MILLISECOND, 0);
            
            // 循环处理每个月
            while (startCal.before(endCal)) {
                // 当前月份的开始
                Date monthStart = startCal.getTime();
                if (monthStart.before(min)) {
                    monthStart = min;
                }
                
                // 计算月份的结束
                Calendar monthEndCal = (Calendar) startCal.clone();
                monthEndCal.set(Calendar.DAY_OF_MONTH, monthEndCal.getActualMaximum(Calendar.DAY_OF_MONTH));
                monthEndCal.set(Calendar.HOUR_OF_DAY, 23);
                monthEndCal.set(Calendar.MINUTE, 59);
                monthEndCal.set(Calendar.SECOND, 59);
                Date monthEnd = monthEndCal.getTime();
                
                // 如果月份结束时间超过了结束时间，使用结束时间
                if (monthEnd.after(max)) {
                    monthEnd = max;
                }
                
                // 格式化月份名称
                String monthName = sdf.format(monthStart);
                
                // 添加到结果列表
                list.add(new DateDimension(monthName, new DateRange(monthStart, monthEnd)).setDimension(this));
                
                // 移动到下个月的第一天
                startCal.add(Calendar.MONTH, 1);
                startCal.set(Calendar.DAY_OF_MONTH, 1);
            }
            
            return list;
            
            
        }
    },
    
    YEAR(4, "年") {
        @Override
        public List<DateDimension> parseRangeDimension(Date startTime, Date endTime) {
            
            SimpleDateFormat sdf_date_time = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy");
            Date min = startTime.getTime() >= endTime.getTime() ? endTime : startTime;
            Date max = startTime.getTime() < endTime.getTime() ? endTime : startTime;
            Calendar startCal = Calendar.getInstance();
            startCal.setTime(min);
            if (sdf_date_time.format(min).endsWith("00:00:00")) {
                // 如果查询参数没有携带时分秒那么. 则将结束时间设置为23:59:59
                startCal.set(Calendar.HOUR_OF_DAY, 0);
                startCal.set(Calendar.MINUTE, 0);
                startCal.set(Calendar.SECOND, 0);
                min = startCal.getTime();
            }
            
            Calendar endCal = Calendar.getInstance();
            endCal.setTime(max);
            if (sdf_date_time.format(max).endsWith("00:00:00")) {
                // 如果查询参数没有携带时分秒那么. 则将结束时间设置为23:59:59
                endCal.set(Calendar.HOUR_OF_DAY, 23);
                endCal.set(Calendar.MINUTE, 59);
                endCal.set(Calendar.SECOND, 59);
                max = endCal.getTime();
            }
            
            int start = Integer.parseInt(sdf.format(min));
            int limit = Integer.parseInt(sdf.format(max));
            List<DateDimension> list = new ArrayList<>();
            
            
            do {
                startCal.set(Calendar.MONTH, 0);
                startCal.set(Calendar.DAY_OF_MONTH, 1);
                startCal.set(Calendar.HOUR_OF_DAY, 0);
                startCal.set(Calendar.MINUTE, 0);
                startCal.set(Calendar.SECOND, 0);
                startCal.set(Calendar.MILLISECOND, 0);
                Date sDate = startCal.getTime();
                if (sDate.before(min)) sDate = min;
                Calendar endCl = (Calendar) startCal.clone();
                endCl.add(Calendar.YEAR, 1);
                endCl.add(Calendar.DAY_OF_YEAR, -1);
                endCl.set(Calendar.HOUR_OF_DAY, 23);
                endCl.set(Calendar.MINUTE, 59);
                endCl.set(Calendar.SECOND, 59);
                Date eDate = endCl.getTime();
                if (eDate.after(max)) {
                    eDate = max;
                }
                list.add(new DateDimension(sdf.format(sDate), new DateRange(sDate, eDate)).setDimension(this));
                startCal.add(Calendar.YEAR, 1);
            } while (startCal.before(endCal));
            
            return list;
        }
    },
    //
    ;
    
    
    @EnumValue
    @com.baomidou.mybatisplus.annotation.EnumValue
    private int dataValue;
    private String dataName;
    
    
    DateDimensionEnum(int value, String name) {
        this.dataValue = value;
        this.dataName = name;
    }
    
    public int getDataValue() {
        return dataValue;
    }
    
    public String getDataName() {
        return dataName;
    }
    
    public abstract List<DateDimension> parseRangeDimension(Date startTime, Date endTime);
    
    public static DateDimensionEnum fromValue(String value) {
        for (DateDimensionEnum item : values()) {
            if (item.name().equals(value) || String.valueOf(item.dataValue).equals(value)) {
                return item;
            }
        }
        return null;
    }
}
